package com.zzyk.main.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.zzyk.main.configuration.exception.UserException;
import com.zzyk.main.mapper.DeviceMapper;
import com.zzyk.main.mapper.MaintenanceInfoMapper;
import com.zzyk.main.model.pojo.AlarmInfo;
import com.zzyk.main.model.pojo.Device;
import com.zzyk.main.model.pojo.MaintenanceInfo;
import com.zzyk.main.model.vo.*;
import com.zzyk.main.service.AlarmInfoService;
import com.zzyk.main.service.ISysUserService;
import com.zzyk.main.service.MaintenanceInfoService;
import com.zzyk.main.service.WebSocketService;
import com.zzyk.main.utils.FTPUtils;
import com.zzyk.main.utils.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author wss_PC
 */
@Service
public class MaintenanceInfoServiceImpl implements MaintenanceInfoService {
    @Value("${ftp.maintenanceDir}")
    private String checkDir;
    @Resource
    private MaintenanceInfoMapper maintenanceInfoMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private AlarmInfoService alarmInfoService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private FTPUtils ftp;

    @Override
    public int deleteByPrimaryKey(Integer id) {
        return maintenanceInfoMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(MaintenanceInfo record) {
        return maintenanceInfoMapper.insert(record);
    }

    @Override
    public int insertSelective(MaintenanceInfo record) throws UserException {
        Integer count = maintenanceInfoMapper.countToDayNumber(record.getSn());
        if (ObjectUtil.isNotNull(count) && count >= 3) {
            throw new UserException("维保次数超限");
        }
        return maintenanceInfoMapper.insertSelective(record);
    }

    @Override
    public MaintenanceInfo selectByPrimaryKey(Integer id) {
        return maintenanceInfoMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(MaintenanceInfo record) {
        return maintenanceInfoMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(MaintenanceInfo record) {
        return maintenanceInfoMapper.updateByPrimaryKey(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertMaintenanceInfo(MaintenanceInfo maintenanceInfo, Integer userId) throws IOException, UserException {
        if (ObjectUtil.isNotNull(userId)) {
            UserInfo user = userService.getUser(userId);
            Device device = deviceMapper.selectOneBySn(maintenanceInfo.getSn(), 1);
            if (ObjectUtil.isNull(device) && !user.getEnterprise().equals(device.getEnterpise())) {
                throw new UserException("未查询到设备信息");
            }
        }
        /*查询当前设备当天是否维保过三次*/
        Integer count = maintenanceInfoMapper.countToDayNumber(maintenanceInfo.getSn());
        if (ObjectUtil.isNotNull(count) && count >= 3) {
            throw new UserException("添加维保次数超限");
        }
        uploadMaintenancePhoto(maintenanceInfo);
        maintenanceInfo.setType(1);

        Device device = deviceMapper.selectOneBySn(maintenanceInfo.getSn(), 1);
        if (ObjectUtil.isNull(device)) {
            throw new UserException("未查询到设备信息，请输入正确的编号");
        }
        if (maintenanceInfo.getSpecies().equals(1)) {
            /*下次维保时间*/
            if (ObjectUtil.isNotNull(device.getLastMaintenance())) {
                DateTime nextMaintenance = DateUtil.offsetDay(device.getLastMaintenance(), device.getMaintenanceCycle());
                /*当前时间*/
                Calendar current = Calendar.getInstance();

                Calendar nextDate = Calendar.getInstance();
                nextDate.setTime(nextMaintenance);
                Integer toMonth = current.get(Calendar.MONTH) + 1;
                Integer toYer = current.get(Calendar.YEAR);
                Integer nextMonth = nextDate.get(Calendar.MONTH) + 1;
                Integer nextYer = nextDate.get(Calendar.YEAR);
                if (toYer > nextYer || (nextYer.equals(toYer) && toMonth > nextMonth)) {
                    maintenanceInfo.setIsExtension(1);
                }
            }
            /*更新设备的上次维保时间*/
            device.setPreviousMaintenance(device.getLastMaintenance());
            device.setLastMaintenance(maintenanceInfo.getMaintenanceTime());
            device.setUpdateTime(DateUtil.date());
            deviceMapper.updateByPrimaryKeySelective(device);
        }
        maintenanceInfoMapper.insertSelective(maintenanceInfo);
       /*  更改本次维保时间、下次维保到期时间
       MaintenanceInfo maintenance = maintenanceInfoMapper.selectOneBySnAndType(maintenanceInfo.getSn(), 2);
        maintenance.setUpdateTime(DateUtil.date());
        maintenance.setMaintenanceTime(maintenanceInfo.getMaintenanceTime());
        maintenance.setNextMaintenanceTime(DateUtil.offsetDay(maintenanceInfo.getMaintenanceTime(), device.getMaintenanceCycle()));
        maintenanceInfoMapper.updateByPrimaryKeySelective(maintenance);*/
    }

    @Override
    public List<MaintenanceInfo> selectAllByParam(String beginTime, String endTime, Integer type, Integer enterprise, String[] areaArr, String name, Integer deviceTyp, Integer[] deviceList) {
        Date bDate = StringUtils.isBlank(beginTime) ? DateUtil.offsetDay(DateUtil.date(), -6) : DateUtil.parse(beginTime);
        Date eDate = StringUtils.isBlank(endTime) ? DateUtil.date() : DateUtil.parse(endTime);
        return maintenanceInfoMapper.selectAllByType(bDate, eDate, type, enterprise, areaArr, name, deviceTyp, deviceList);
    }

    @Override
    @Transactional
    public void updateByPrimaryKeyAndFileUpload(MaintenanceInfo maintenanceInfo, Integer userId) throws IOException, UserException {
        if (ObjectUtil.isNotNull(userId)) {
            UserInfo user = userService.getUser(userId);
            Device device = deviceMapper.selectOneBySn(maintenanceInfo.getSn(), 1);
            if (!user.getEnterprise().equals(device.getEnterpise())) {
                throw new UserException("未查询到设备信息");
            }
        }

        uploadMaintenancePhoto(maintenanceInfo);
        maintenanceInfo.setUpdateTime(DateUtil.date());
        maintenanceInfoMapper.updateByPrimaryKeySelective(maintenanceInfo);
        if (1 == maintenanceInfo.getSpecies()) {
            Device device = deviceMapper.selectOneBySn(maintenanceInfo.getSn(), 1);
            device.setUpdateTime(DateUtil.date());
            device.setLastMaintenance(maintenanceInfo.getMaintenanceTime());
            deviceMapper.updateByPrimaryKeySelective(device);
        }
       /* 更改本次维保时间、下次维保到期时间
       MaintenanceInfo maintenance = maintenanceInfoMapper.selectOneBySnAndType(maintenanceInfo.getSn(), 2);
        maintenance.setUpdateTime(DateUtil.date());
        maintenance.setMaintenanceTime(maintenanceInfo.getMaintenanceTime());
        maintenance.setNextMaintenanceTime(DateUtil.offsetDay(maintenanceInfo.getMaintenanceTime(), device.getMaintenanceCycle()));
        maintenanceInfoMapper.updateByPrimaryKeySelective(maintenance);*/
    }


  /*  @Override
    public List<CommonCount> findMaintenanceStatusThisMonth() {
        List<CommonCount> list = new ArrayList<>();
        CommonCount should = maintenanceInfoMapper.selectCountShould();
        CommonCount completed = maintenanceInfoMapper.selectCountCompleted();
        CommonCount TODO = new CommonCount();
        CommonCount extension = maintenanceInfoMapper.selectCountExtension();
        TODO.setName("待维保");
        TODO.setValue(Integer.parseInt(should.getValue()) - Integer.parseInt(completed.getValue()) + "");
        list.add(should);
        list.add(TODO);
        list.add(extension);
        list.add(completed);
        return list;
    }*/

    @Override
    @Transactional
    public DateAndString selectMaintenanceInfoByDId(Integer id) {
        DateAndString dateAndString = new DateAndString();
        Device device = deviceMapper.selectByPrimaryKey(id);
        if (ObjectUtil.isNull(device)) {
            return null;
        }
        Date lastMaintenance = device.getLastMaintenance();
        DateTime dateTime = DateUtil.offsetDay(ObjectUtil.isNull(lastMaintenance) ? device.getCreateTime() : device.getLastMaintenance(), device.getMaintenanceCycle());
        //        没有维保记录会报错
        Long between = DateUtil.between(DateUtil.beginOfDay(new Date()), DateUtil.beginOfDay(dateTime), DateUnit.DAY, false);
        dateAndString.setDate(device.getLastMaintenance());
        dateAndString.setStr(between.toString());
        return dateAndString;
    }

    @Override
    @Transactional
    public void deleteMaintenanceByPrimaryKey(Integer id) {
        /*首先去查询这条维保信息*/
        MaintenanceInfo maintenanceInfo = selectByPrimaryKey(id);
        /*删除维保记录*/
        deleteByPrimaryKey(id);
        /*查询最新的一条维保记录*/
        MaintenanceInfo info = maintenanceInfoMapper.selectByDeviceSnTopOne(maintenanceInfo.getSn());
        if (ObjectUtil.isNotNull(info)) {
            Device device = deviceMapper.selectOneBySn(info.getSn(), 1);
            if (ObjectUtil.isNotNull(device)) {
                device.setLastMaintenance(info.getMaintenanceTime());
                device.setUpdateTime(DateUtil.date());
                deviceMapper.updateByPrimaryKeySelective(device);
            }
        } else {
            Device device = deviceMapper.selectOneBySn(maintenanceInfo.getSn(), 1);
            if (ObjectUtil.isNotNull(device)) {
                device.setLastMaintenance(device.getCreateTime());
                device.setUpdateTime(DateUtil.date());
                deviceMapper.updateByPrimaryKeySelective(device);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void findNeedMaintenanceToday() throws IOException {
        List<MaintenanceView> deviceMaintenance = deviceMapper.getDeviceMaintenance(null, null, null);
        for (MaintenanceView maintenanceView : deviceMaintenance) {
            /*上次维保时间*/
            if (ObjectUtil.isNull(maintenanceView.getLastMaintenance())) {
                maintenanceView.setLastMaintenance(maintenanceView.getCreateTime());
            }
            Date nextMaintenanceDate = DateUtil.offsetDay(maintenanceView.getLastMaintenance(), maintenanceView.getCycle());
            String nextMaintenanceStr = DateUtil.formatDate(nextMaintenanceDate);
            long between = DateUtil.between(DateUtil.beginOfDay(DateUtil.date()), DateUtil.beginOfDay(nextMaintenanceDate), DateUnit.DAY, false);
            if (between <= 0) {
                AlarmInfo alarmInfo = new AlarmInfo();
                alarmInfo.setEid(maintenanceView.getEId());
                alarmInfo.setDid(maintenanceView.getId());
                alarmInfo.setGrade(0);
                alarmInfo.setStatus(1);
                alarmInfo.setContent(nextMaintenanceStr);
                alarmInfo.setResult(between + "");
                alarmInfo.setCreatetime(new Date());
                alarmInfoService.insertSelective(alarmInfo);
                WebSocketService.sendMessageToAll(maintenanceView.getEId().toString());
            }
        }
    }

    @Override
    public List<MaintenanceInfo> findDateRangeMaintenance(String dateTime, Integer enterprise, Integer[] deviceList) {
        Date bDate;
        Date eDate;
        if (StringUtils.isNotBlank(dateTime)) {
            String[] time = dateTime.split(" ~ ");
            bDate = DateUtil.parseDate(time[0]);
            eDate = DateUtil.parseDate(time[1]);
        } else {
            bDate = DateUtil.offsetDay(new Date(), -30);
            eDate = DateUtil.date();
        }
        return maintenanceInfoMapper.selectAllByType(bDate, eDate, 1, enterprise, null, null, null, deviceList);
    }

    @Override
    public Message findConclusion(String dateTime, Integer enterprise, Integer[] deviceList) {
        Date bDate;
        Date eDate;
        if (StringUtils.isNotBlank(dateTime)) {
            String[] time = dateTime.split(" ~ ");
            bDate = DateUtil.parseDate(time[0]);
            eDate = DateUtil.parseDate(time[1]);
        } else {
            bDate = DateUtil.offsetDay(new Date(), -30);
            eDate = DateUtil.date();
        }
        KeyValue keyValue = maintenanceInfoMapper.countConclusion(bDate, eDate, enterprise, 5, 1, deviceList);
        String device1 = "";
        String device2 = "";
        Integer max = 0;
        if (ObjectUtil.isNotNull(keyValue)) {
            Device device = deviceMapper.selectOneBySn(keyValue.getDate(), 1);
            device1 = device.getName();
            max = Integer.valueOf(keyValue.getValue().toString());
        }
        KeyValue keyValue2 = maintenanceInfoMapper.countConclusion(bDate, eDate, enterprise, 4, 1, deviceList);
        if (ObjectUtil.isNotNull(keyValue2)) {
            Device device = deviceMapper.selectOneBySn(keyValue2.getDate(), 1);
            device2 = device.getName();
        }
        return Message.success().addData("device1", device1).addData("device2", device2).addData("max", max);
    }

    @Override
    public List<MaintenanceView> findFailureRanking(String dateTime, Integer enterprise, Integer[] deviceList) {
        Date bDate;
        Date eDate;
        if (StringUtils.isNotBlank(dateTime)) {
            String[] time = dateTime.split(" ~ ");
            bDate = DateUtil.parseDate(time[0]);
            eDate = DateUtil.parseDate(time[1]);
        } else {
            bDate = DateUtil.offsetDay(new Date(), -30);
            eDate = DateUtil.date();
        }
        return maintenanceInfoMapper.selectFailureRanking(bDate, eDate, enterprise, deviceList);
    }

    @Override
    public List<MaintenanceInfo> findInfoList(String dateTime, Integer enterprise, Integer[] deviceList) {
        Date bDate;
        Date eDate;
        if (StringUtils.isNotBlank(dateTime)) {
            String[] time = dateTime.split(" ~ ");
            bDate = DateUtil.parseDate(time[0]);
            eDate = DateUtil.parseDate(time[1]);
        } else {
            bDate = DateUtil.offsetDay(new Date(), -30);
            eDate = DateUtil.date();
        }
        return maintenanceInfoMapper.selectInfoList(bDate, eDate, enterprise, deviceList);
    }


    @Override
    public List<Map<Object, Object>> countMaintenanceInfoByParam(String beginTime, String endTime, Integer type, Integer enterprise, String[] areaArr, String name, Integer deviceType, Integer[] deviceList) {
        Date bDate = StringUtils.isBlank(beginTime) ? DateUtil.offsetDay(DateUtil.date(), -6) : DateUtil.parse(beginTime);
        Date eDate = StringUtils.isBlank(endTime) ? DateUtil.date() : DateUtil.parse(endTime);
        return maintenanceInfoMapper.countMaintenanceInfoByParam(bDate,eDate,type,enterprise,areaArr,name,deviceType,deviceList);
    }

    @Override
    public List<Map<Object, Object>> countMaintenanceInfoByParamApi(String beginTime, String endTime, Integer type, Integer enterprise, Object o, String name, Integer deviceType, Integer[] deviceList) {
        Date bDate = StringUtils.isBlank(beginTime) ? DateUtil.offsetDay(DateUtil.date(), -6) : DateUtil.parse(beginTime);
        Date eDate = StringUtils.isBlank(endTime) ? DateUtil.date() : DateUtil.parse(endTime);
        return maintenanceInfoMapper.countMaintenanceInfoByParamApi(bDate,eDate,type,enterprise,name,deviceType,deviceList);
    }

    // 上传并更新维保设备照片 （仅更新对象的image属性）
    private void uploadMaintenancePhoto(MaintenanceInfo maintenanceInfo) throws IOException {
        if (maintenanceInfo.getPhotoFile() != null && !"".equals(maintenanceInfo.getPhotoFile().getOriginalFilename())) {
            MultipartFile file = maintenanceInfo.getPhotoFile();
            String filename = IdUtil.fastSimpleUUID() + "." + FileUtils.getExt(file.getOriginalFilename());
            maintenanceInfo.setImage(checkDir + "/" + filename);
            ftp.upload(file.getInputStream(), filename, checkDir);
            if (ObjectUtil.isNotNull(maintenanceInfo.getThumbnail())) {
                ftp.upload(maintenanceInfo.getThumbnail().getInputStream(), "min" + filename, checkDir);
            } else {
                ftp.upload(file.getInputStream(), "min" + filename, checkDir);
            }
        }
    }

}







